자바 플랫폼과 함께 제공되는 표준 레이아웃 관리자 중 하나가 BoxLayout
입니다. 이 관리자를 사용하여 단일 행 또는 열의 구성요소를 컨테이너에 배치할 수 있습니다. 그리 복잡하지 않은 레이아웃 관리자인 듯 하나, Box
및 해당 glue와 strut를 활용하면 충분하리라 생각할 것입니다. 하지만 이것이 전부는 아닙니다. 기본 구성요소의 수직 및
수평 정렬을 통해 컨테이너 내부에서 구성요소의 위치를 더 제어할 수 있습니다. 이 점을 모두 살펴보겠습니다.
일반적인 사용
BoxLayout은 레이아웃 관리자를 생성하고 이를 Container
와 연결하면 되는 대부분의 레이아웃 관리자와 다릅니다. BoxLayout
구성자에서는 Container
를 레이아웃 관리자의 구성자에 전달하여 각각 다른 구성요소에 대한 참조를 포함해야 합니다. 이 작업이 번거롭게 여겨질 수도 있으므로, Box
컨테이너를 사용하는 경우가 더 많습니다. static
메소드 중 하나를 통해 수평 또는 수직 배열된 Box
를 요청하면 되기 때문입니다.
Box vertical = Box.createVerticalBox();
Box horizontal = Box.createHorizontalBox();
둘 다 배후에서는 BoxLayout
을 사용하면서 추가된 구성요소를 방향에 따라 알맞은 액세스에 배치합니다. 수직 박스는 모든 것을 하나의 열에, 수평 박스는 하나의 행에 배치합니다. BoxLayout
(그리고 Box
)을 GridLayout
과 비교하려면 간단한 설명이 필요합니다. GridLayout
에서 제어하는 컨테이너에 여러 구성요소를 배치할 경우 모든 구성요소는 동일한 크기여야 합니다. BoxLayout
에서는 그렇지 않으며, 구성요소 최대 기본 크기가 인정됩니다.
Strut와 Glue
Box 클래스에서는 두 가지 지원 구성요소를 생성하는데, 고정 크기의 필러 영역인 strut와 확장 가능한 영역인
glue입니다. strut를 사용하면 고정된 간격으로, glue를 사용하면 가용 공간에 따라 확대/축소되는 영역으로 컨테이너에
구성요소를 배치할 수 있습니다. GridBagConstraints
및 GridBagLayout
을 사용하면 동일한 효과를 얻을 수 있으나, 쉽지 않습니다.
이를 확인하기 위해 다음 첫 번째 프로그램에서는 맨 위의 두 구성요소 사이에 25픽셀의 strut를, 맨 아래 두 구성요소 사이에는 10픽셀의 strut를 생성합니다.
import java.awt.*;
import javax.swing.*;
public class VerticalBoxTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Vertical Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createVerticalBox();
box.add(new Button("Top"));
box.add(Box.createVerticalStrut(25));
box.add(new Button("Middle"));
box.add(Box.createVerticalStrut(10));
box.add(new Button("Bottom"));
frame.add(box, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
이 코드를 컴파일하고 실행하여 창 크기가 증감할 때 구성요소의 크기가 어떻게 바뀌는지 확인하십시오. 구성요소 사이의 거리는
바뀌지 않고, 예약된 strut 공간과 일치합니다. 이 예제에서는 곧 나올 구성요소 정렬에 대한 설명을 피하기 위해 JButton
대신 <code>Button</code>을 사용합니다.
수평 박스와 glue를 사용하면 비슷한 결과를 얻지만, 이번에는 strut처럼 고정된 크기를 유지하는 것이 아니라 glue의 크기가 증가하면서 추가 공간을 차지합니다.
import java.awt.*;
import javax.swing.*;
public class HorizontalBoxTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Horizontal Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(new JButton("Left"));
box.add(new JButton("Right"));
frame.add(box, BorderLayout.NORTH);
box = Box.createHorizontalBox();
box.add(new JButton("Left"));
box.add(Box.createHorizontalGlue());
box.add(new JButton("Right"));
frame.add(box, BorderLayout.CENTER);
box = Box.createHorizontalBox();
box.add(new JButton("Left"));
box.add(new JButton("Right"));
box.add(Box.createHorizontalGlue());
frame.add(box, BorderLayout.SOUTH);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
크게 혼동스럽지 않다면, 이제 JButton
구성요소를 사용하는 경우를 살펴보겠습니다.
정렬
컨테이너 내부의 구성요소가 다른 크기일 경우 또는 컨테이너의 높이/너비가 수직 박스에 필요한 것보다 넓거나 수평 박스에 필요한 것보다 높을 경우, Box/BoxLayout
에서는 흥미로운 상황이 벌어집니다. 즉 긴 열에서 너비가 다른 구성요소는 어떻게 됩니까? 그리고 높이가 다른 구성요소로 이루어진 넓은 행이 있다면 어떻게 됩니까?
여기서 다른 구성요소 정렬 방법이 진가를 발휘합니다. 각 Swing 구성요소에는 X-alignment
설정과 Y-alignment
설정이 있습니다. get/setAlignmentX()
및 get/setAlignmentY()
메소드 덕분입니다. 각 설정의 범위는 0
부터 1.0
까지입니다. BoxLayout
의 방향에 따라 0
은 왼쪽 또는 맨 위 정렬을, 1
은 오른쪽 또는 맨 아래 정렬을 의미합니다. Component
클래스에 사용 가능한 상수가 있으므로, 어떤 값이 오른쪽 및 왼쪽 정렬인지 알 필요는 없습니다. 그러나 그 사이에 뭔가를 둘 것인지 안다면 도움이 됩니다.
수직 박스에서 크기가 다른 버튼의 오른쪽, 왼쪽 및 가운데 특성을 보여주기 위해, 다음 프로그램에서는 각각 왼쪽, 가운데 및 오른쪽 정렬 버튼이 있는 박스 3개를 생성합니다.
import java.awt.*;
import javax.swing.*;
public class AlignX {
private static Container makeIt(String labelChar, float alignment) {
Box box = Box.createVerticalBox();
for (int i=1; i<6; i++) {
String label = makeLabel(labelChar, i*2);
JButton button = new JButton(label);
button.setAlignmentX(alignment);
box.add(button);
}
return box;
}
private static String makeLabel(String s, int length) {
StringBuffer buff = new StringBuffer(length);
for (int i=0; i<length; i++) {
buff.append(s);
}
return buff.toString();
}
public static void main(String args[]) {
JFrame frame = new JFrame("X Alignment");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container panel1 = makeIt("L", Component.LEFT_ALIGNMENT);
Container panel2 = makeIt("C", Component.CENTER_ALIGNMENT);
Container panel3 = makeIt("R", Component.RIGHT_ALIGNMENT);
frame.setLayout(new FlowLayout());
frame.add(panel1);
frame.add(panel2);
frame.add(panel3);
frame.pack();
frame.setVisible(true);
}
}
이
제 약간 뒤섞어서 정렬별로 하나씩, 3개의 버튼이 있는 수직 박스 하나를 만들겠습니다. 추가 가용 공간이 있음을 확인하기 위해
화면 너비가 넓어집니다. 개념상으로는 왼쪽 정렬의 구성요소가 컨테이너의 왼쪽으로, 오른쪽 정렬의 구성요소가 컨테이너의 오른쪽으로
정렬되리라 생각할 것입니다. 하지만 그렇지 않습니다. 서로 다른 구성요소 정렬이 있으면 컨테이너의 가운데에 정렬됩니다. 즉 왼쪽
정렬의 경우, 구성요소의 왼쪽 가장자리가 숨겨진 컨테이너 중앙선에 옵니다. 오른쪽 정렬에서는 오른쪽 가장자리가 옵니다.
다음은 이를 확인하기 위한 프로그램입니다.
import java.awt.*;
import javax.swing.*;
public class AlignX2 {
public static void main(String args[]) {
JFrame frame = new JFrame("X Alignment");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createVerticalBox();
JButton button = new JButton("LL");
button.setAlignmentX(Component.LEFT_ALIGNMENT);
box.add(button);
button = new JButton("CC");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
box.add(button);
button = new JButton("RR");
button.setAlignmentX(Component.RIGHT_ALIGNMENT);
box.add(button);
frame.add(box, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);}
}
이를 입증해 주는 화면입니다.
다른 방향의 작업에서는 맨 위 정렬의 경우 구성요소의 맨 위가 가상의 중심선에, 즉 가운데 아래에 옵니다.
이런 식으로 정렬을 혼합하더라도 제대로 작동하지만, 익숙해지는 데 시간이 걸립니다. 모든 정렬이 동일하지 않는 한 정렬이 예상한 위치에 오지 않을 수도 있으며, 컨테이너 중심선이 아니라 컨테이너의 경계에 맞춰지기 때문입니다.
아직도 잘 이해되지 않는다면 이전의 프로그램을 수정하여 x
및 y
정렬의 조합을 더 시도해 보십시오. 물론 모든 시도가 생각대로 되지 않는다면 언제든지 GridBagLayout
을 사용하면 됩니다.
이 글의 영문 원본은
http://blogs.sun.com/CoreJavaTechTips/entry/getting_to_know_boxlayout
에서 보실 수 있습니다.
출처 : http://sdnkorea.com/blog/529